package cloud.seri.iot.manager.web.rest

import cloud.seri.iot.manager.SeriIotManagerApp

import cloud.seri.iot.manager.config.SecurityBeanOverrideConfiguration

import cloud.seri.iot.manager.domain.Commodity
import cloud.seri.iot.manager.repository.CommodityRepository
import cloud.seri.iot.manager.service.CommodityService
import cloud.seri.iot.manager.service.dto.CommodityDTO
import cloud.seri.iot.manager.service.mapper.CommodityMapper
import cloud.seri.iot.manager.web.rest.errors.ExceptionTranslator

import kotlin.test.assertNotNull

import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.MockitoAnnotations
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.data.web.PageableHandlerMethodArgumentResolver
import org.springframework.http.MediaType
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
import org.springframework.test.context.junit4.SpringRunner
import org.springframework.test.web.servlet.MockMvc
import org.springframework.test.web.servlet.setup.MockMvcBuilders
import org.springframework.validation.Validator



import cloud.seri.iot.manager.web.rest.TestUtil.createFormattingConversionService
import org.assertj.core.api.Assertions.assertThat
import org.hamcrest.Matchers.hasItem
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status

/**
 * Test class for the CommodityResource REST controller.
 *
 * @see CommodityResource
 */
@RunWith(SpringRunner::class)
@SpringBootTest(classes = [SecurityBeanOverrideConfiguration::class, SeriIotManagerApp::class])
class CommodityResourceIT {

    @Autowired
    private lateinit var commodityRepository: CommodityRepository

    @Autowired
    private lateinit var commodityMapper: CommodityMapper

    @Autowired
    private lateinit var commodityService: CommodityService

    @Autowired
    private lateinit var jacksonMessageConverter: MappingJackson2HttpMessageConverter

    @Autowired
    private lateinit var pageableArgumentResolver: PageableHandlerMethodArgumentResolver

    @Autowired
    private lateinit var exceptionTranslator: ExceptionTranslator

    @Autowired
    private lateinit var validator: Validator

    private lateinit var restCommodityMockMvc: MockMvc

    private lateinit var commodity: Commodity

    @Before
    fun setup() {
        MockitoAnnotations.initMocks(this)
        val commodityResource = CommodityResource(commodityService)
        this.restCommodityMockMvc = MockMvcBuilders.standaloneSetup(commodityResource)
            .setCustomArgumentResolvers(pageableArgumentResolver)
            .setControllerAdvice(exceptionTranslator)
            .setConversionService(createFormattingConversionService())
            .setMessageConverters(jacksonMessageConverter)
            .setValidator(validator).build()
    }

    @Before
    fun initTest() {
        commodityRepository.deleteAll()
        commodity = createEntity()
    }

    @Test
    fun createCommodity() {
        val databaseSizeBeforeCreate = commodityRepository.findAll().size

        // Create the Commodity
        val commodityDTO = commodityMapper.toDto(commodity)
        restCommodityMockMvc.perform(
            post("/api/commodities")
                .contentType(TestUtil.APPLICATION_JSON_UTF8)
                .content(TestUtil.convertObjectToJsonBytes(commodityDTO))
        ).andExpect(status().isCreated)

        // Validate the Commodity in the database
        val commodityList = commodityRepository.findAll()
        assertThat(commodityList).hasSize(databaseSizeBeforeCreate + 1)
        val testCommodity = commodityList[commodityList.size - 1]
        assertThat(testCommodity.name).isEqualTo(DEFAULT_NAME)
        assertThat(testCommodity.originalPrice).isEqualTo(DEFAULT_ORIGINAL_PRICE)
        assertThat(testCommodity.currentPrice).isEqualTo(DEFAULT_CURRENT_PRICE)
        assertThat(testCommodity.description).isEqualTo(DEFAULT_DESCRIPTION)
        assertThat(testCommodity.pic).isEqualTo(DEFAULT_PIC)
        assertThat(testCommodity.status).isEqualTo(DEFAULT_STATUS)
    }

    @Test
    fun createCommodityWithExistingId() {
        val databaseSizeBeforeCreate = commodityRepository.findAll().size

        // Create the Commodity with an existing ID
        commodity.id = "existing_id"
        val commodityDTO = commodityMapper.toDto(commodity)

        // An entity with an existing ID cannot be created, so this API call must fail
        restCommodityMockMvc.perform(
            post("/api/commodities")
                .contentType(TestUtil.APPLICATION_JSON_UTF8)
                .content(TestUtil.convertObjectToJsonBytes(commodityDTO))
        ).andExpect(status().isBadRequest)

        // Validate the Commodity in the database
        val commodityList = commodityRepository.findAll()
        assertThat(commodityList).hasSize(databaseSizeBeforeCreate)
    }


    @Test
    fun checkNameIsRequired() {
        val databaseSizeBeforeTest = commodityRepository.findAll().size
        // set the field null
        commodity.name = null

        // Create the Commodity, which fails.
        val commodityDTO = commodityMapper.toDto(commodity)

        restCommodityMockMvc.perform(
            post("/api/commodities")
                .contentType(TestUtil.APPLICATION_JSON_UTF8)
                .content(TestUtil.convertObjectToJsonBytes(commodityDTO))
        ).andExpect(status().isBadRequest)

        val commodityList = commodityRepository.findAll()
        assertThat(commodityList).hasSize(databaseSizeBeforeTest)
    }

    @Test
    fun checkCurrentPriceIsRequired() {
        val databaseSizeBeforeTest = commodityRepository.findAll().size
        // set the field null
        commodity.currentPrice = null

        // Create the Commodity, which fails.
        val commodityDTO = commodityMapper.toDto(commodity)

        restCommodityMockMvc.perform(
            post("/api/commodities")
                .contentType(TestUtil.APPLICATION_JSON_UTF8)
                .content(TestUtil.convertObjectToJsonBytes(commodityDTO))
        ).andExpect(status().isBadRequest)

        val commodityList = commodityRepository.findAll()
        assertThat(commodityList).hasSize(databaseSizeBeforeTest)
    }

    @Test
    fun getAllCommodities() {
        // Initialize the database
        commodityRepository.save(commodity)

        // Get all the commodityList
        restCommodityMockMvc.perform(get("/api/commodities?sort=id,desc"))
            .andExpect(status().isOk)
            .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
            .andExpect(jsonPath("$.[*].id").value(hasItem(commodity.id)))
            .andExpect(jsonPath("$.[*].name").value(hasItem(DEFAULT_NAME)))
            .andExpect(jsonPath("$.[*].originalPrice").value(hasItem(DEFAULT_ORIGINAL_PRICE)))
            .andExpect(jsonPath("$.[*].currentPrice").value(hasItem(DEFAULT_CURRENT_PRICE)))
            .andExpect(jsonPath("$.[*].description").value(hasItem(DEFAULT_DESCRIPTION)))
            .andExpect(jsonPath("$.[*].pic").value(hasItem(DEFAULT_PIC)))
            .andExpect(jsonPath("$.[*].status").value(hasItem(DEFAULT_STATUS)))
    }
    
    @Test
    fun getCommodity() {
        // Initialize the database
        commodityRepository.save(commodity)

        val id = commodity.id
        assertNotNull(id)

        // Get the commodity
        restCommodityMockMvc.perform(get("/api/commodities/{id}", id))
            .andExpect(status().isOk)
            .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
            .andExpect(jsonPath("$.id").value(id))
            .andExpect(jsonPath("$.name").value(DEFAULT_NAME))
            .andExpect(jsonPath("$.originalPrice").value(DEFAULT_ORIGINAL_PRICE))
            .andExpect(jsonPath("$.currentPrice").value(DEFAULT_CURRENT_PRICE))
            .andExpect(jsonPath("$.description").value(DEFAULT_DESCRIPTION))
            .andExpect(jsonPath("$.pic").value(DEFAULT_PIC))
            .andExpect(jsonPath("$.status").value(DEFAULT_STATUS))
    }

    @Test
    fun getNonExistingCommodity() {
        // Get the commodity
        restCommodityMockMvc.perform(get("/api/commodities/{id}", Long.MAX_VALUE))
            .andExpect(status().isNotFound)
    }

    @Test
    fun updateCommodity() {
        // Initialize the database
        commodityRepository.save(commodity)

        val databaseSizeBeforeUpdate = commodityRepository.findAll().size

        // Update the commodity
        val id = commodity.id
        assertNotNull(id)
        val updatedCommodity = commodityRepository.findById(id).get()
        updatedCommodity.name = UPDATED_NAME
        updatedCommodity.originalPrice = UPDATED_ORIGINAL_PRICE
        updatedCommodity.currentPrice = UPDATED_CURRENT_PRICE
        updatedCommodity.description = UPDATED_DESCRIPTION
        updatedCommodity.pic = UPDATED_PIC
        updatedCommodity.status = UPDATED_STATUS
        val commodityDTO = commodityMapper.toDto(updatedCommodity)

        restCommodityMockMvc.perform(
            put("/api/commodities")
                .contentType(TestUtil.APPLICATION_JSON_UTF8)
                .content(TestUtil.convertObjectToJsonBytes(commodityDTO))
        ).andExpect(status().isOk)

        // Validate the Commodity in the database
        val commodityList = commodityRepository.findAll()
        assertThat(commodityList).hasSize(databaseSizeBeforeUpdate)
        val testCommodity = commodityList[commodityList.size - 1]
        assertThat(testCommodity.name).isEqualTo(UPDATED_NAME)
        assertThat(testCommodity.originalPrice).isEqualTo(UPDATED_ORIGINAL_PRICE)
        assertThat(testCommodity.currentPrice).isEqualTo(UPDATED_CURRENT_PRICE)
        assertThat(testCommodity.description).isEqualTo(UPDATED_DESCRIPTION)
        assertThat(testCommodity.pic).isEqualTo(UPDATED_PIC)
        assertThat(testCommodity.status).isEqualTo(UPDATED_STATUS)
    }

    @Test
    fun updateNonExistingCommodity() {
        val databaseSizeBeforeUpdate = commodityRepository.findAll().size

        // Create the Commodity
        val commodityDTO = commodityMapper.toDto(commodity)

        // If the entity doesn't have an ID, it will throw BadRequestAlertException
        restCommodityMockMvc.perform(
            put("/api/commodities")
                .contentType(TestUtil.APPLICATION_JSON_UTF8)
                .content(TestUtil.convertObjectToJsonBytes(commodityDTO))
        ).andExpect(status().isBadRequest)

        // Validate the Commodity in the database
        val commodityList = commodityRepository.findAll()
        assertThat(commodityList).hasSize(databaseSizeBeforeUpdate)
    }

    @Test
    fun deleteCommodity() {
        // Initialize the database
        commodityRepository.save(commodity)

        val databaseSizeBeforeDelete = commodityRepository.findAll().size

        val id = commodity.id
        assertNotNull(id)

        // Delete the commodity
        restCommodityMockMvc.perform(
            delete("/api/commodities/{id}", id)
                .accept(TestUtil.APPLICATION_JSON_UTF8)
        ).andExpect(status().isNoContent)

        // Validate the database is empty
        val commodityList = commodityRepository.findAll()
        assertThat(commodityList).hasSize(databaseSizeBeforeDelete - 1)
    }

    @Test
    fun equalsVerifier() {
        TestUtil.equalsVerifier(Commodity::class.java)
        val commodity1 = Commodity()
        commodity1.id = "id1"
        val commodity2 = Commodity()
        commodity2.id = commodity1.id
        assertThat(commodity1).isEqualTo(commodity2)
        commodity2.id = "id2"
        assertThat(commodity1).isNotEqualTo(commodity2)
        commodity1.id = null
        assertThat(commodity1).isNotEqualTo(commodity2)
    }

    @Test
    fun dtoEqualsVerifier() {
        TestUtil.equalsVerifier(CommodityDTO::class.java)
        val commodityDTO1 = CommodityDTO()
        commodityDTO1.id = "id1"
        val commodityDTO2 = CommodityDTO()
        assertThat(commodityDTO1).isNotEqualTo(commodityDTO2)
        commodityDTO2.id = commodityDTO1.id
        assertThat(commodityDTO1).isEqualTo(commodityDTO2)
        commodityDTO2.id = "id2"
        assertThat(commodityDTO1).isNotEqualTo(commodityDTO2)
        commodityDTO1.id = null
        assertThat(commodityDTO1).isNotEqualTo(commodityDTO2)
    }

    companion object {

        private const val DEFAULT_NAME: String = "AAAAAAAAAA"
        private const val UPDATED_NAME = "BBBBBBBBBB"

        private const val DEFAULT_ORIGINAL_PRICE: Int = 1
        private const val UPDATED_ORIGINAL_PRICE: Int = 2

        private const val DEFAULT_CURRENT_PRICE: Int = 1
        private const val UPDATED_CURRENT_PRICE: Int = 2

        private const val DEFAULT_DESCRIPTION: String = "AAAAAAAAAA"
        private const val UPDATED_DESCRIPTION = "BBBBBBBBBB"

        private const val DEFAULT_PIC: String = "AAAAAAAAAA"
        private const val UPDATED_PIC = "BBBBBBBBBB"

        private const val DEFAULT_STATUS: Int = 1
        private const val UPDATED_STATUS: Int = 2

        /**
         * Create an entity for this test.
         *
         * This is a static method, as tests for other entities might also need it,
         * if they test an entity which requires the current entity.
         */
        @JvmStatic
        fun createEntity(): Commodity {
            val commodity = Commodity(
                name = DEFAULT_NAME,
                originalPrice = DEFAULT_ORIGINAL_PRICE,
                currentPrice = DEFAULT_CURRENT_PRICE,
                description = DEFAULT_DESCRIPTION,
                pic = DEFAULT_PIC,
                status = DEFAULT_STATUS
            )
            return commodity
        }
    }
}
